package com.imooc.mymall.controller;

import com.imooc.mymall.domain.common.PageResult;
import com.imooc.mymall.domain.common.ResponseResult;
import com.imooc.mymall.domain.common.PageQuery;
import com.imooc.mymall.domain.dto.UserDTO;
import com.imooc.mymall.domain.dto.UserQueryDTO;
import com.imooc.mymall.domain.vo.UserVO;
import com.imooc.mymall.exception.ErrorCodeEnum;
import com.imooc.mymall.service.ExcelExportService;
import com.imooc.mymall.service.UserService;
import com.imooc.mymall.util.InsertValidationGroup;
import com.imooc.mymall.util.UpdateValidationGroup;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <h1>用户Controller</h1>
 * @Author: crowsjian
 * @Date: 2020/7/11 14:03
 */
@RestController
@RequestMapping("/api/users")
@Slf4j
@Validated
@Api(
        value = "用户管理Controller",
        protocols = "http,https",
        hidden = false
)
public class UserController {

    @Autowired
    private ExcelExportService excelExportService;

    @Autowired
    private UserService userService;

    /**
     * <h2>新增用户</h2>
     * POST /api/user UserDTO
     * @param userDTO
     * @return
     */
    @CacheEvict(cacheNames = "users-cache",allEntries = true)//allEntries所有进入该方法都会清缓存
    @PostMapping
    public ResponseResult save(@Validated(InsertValidationGroup.class)@RequestBody UserDTO userDTO){
        int save = userService.save(userDTO);
        if(save == 1){
            return ResponseResult.success("新增成功！");
        }else{
            return ResponseResult.failure(ErrorCodeEnum.INSERT_FAILURE);
        }
    }

    /**
     * <h2>更新用户信息</h2>
     * PUT /api/users/{id}
     * @param id
     * @param userDTO
     * @return
     */
    @PutMapping("/{id}")
    @ApiOperation(
            value = "更新用户信息",
            notes = "备注说明信息",
            response = ResponseResult.class,
            httpMethod = "PUT"
    )
    @ApiImplicitParams({
        @ApiImplicitParam(
                name = "id",
                value = "参数说明，用户主键",
                required = true,
                paramType = "path",
                dataType = "Long",
                example = "1123"
        ),@ApiImplicitParam(
            name = "userDTO",
            value = "用户信息",
            required = true,
            paramType = "body",
            dataType = "UserDTO",
            dataTypeClass = UserDTO.class
         )
    })
    @ApiResponses({
            @ApiResponse(
                    code = 0000,message = "操作成功"
            ),
            @ApiResponse(
                    code = 3004,message = "更新失败"
            )
    })
    public ResponseResult update(@NotNull @PathVariable("id") Long id,
                                 @Validated(UpdateValidationGroup.class) @RequestBody UserDTO userDTO){
        int update = userService.update(id,userDTO);
        if(update == 1){
            return ResponseResult.success("更新成功！");
        }else{
            return ResponseResult.failure(ErrorCodeEnum.UPDATE_FAILURE);
        }
    }

    /**
     * <h2>删除用户信息</h2>
     * DELETE /api/users/{id}
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public ResponseResult delete(@NotNull(message = "用户ID不能为空！")@PathVariable("id") Long id){
        int delete = userService.delete(id);
        if(delete == 1){
            return ResponseResult.success("删除成功！");
        }else{
            return ResponseResult.failure(ErrorCodeEnum.DELETE_FAILURE);
        }
    }

    /**
     * <h2>查询用户信息</h2>
     * @param pageNo
     * @param pageSize
     * @param query
     * @return
     */
    @Cacheable(cacheNames = "users-cache")
    @GetMapping
    public ResponseResult<PageResult> query(@NotNull Integer pageNo,
                                            @NotNull Integer pageSize,
                                            @Validated UserQueryDTO query){
        log.info("未使用缓存！");
        // 构造查询条件
        PageQuery<UserQueryDTO> pageQuery = new PageQuery<>();
        pageQuery.setPageNo(pageNo);
        pageQuery.setPageSize(pageSize);
        pageQuery.setQuery(query);
        // 查询
        PageResult<List<UserDTO>> pageResult = userService.query(pageQuery);
        // 实体转换
        List<UserVO> userVOList = Optional.ofNullable(pageResult.getData())
                .map(List::stream)
                .orElseGet(Stream::empty)
                .map(userDTO -> {
                    UserVO userVO = new UserVO();
                    BeanUtils.copyProperties(userDTO,userVO);
                    // 对特殊字段的处理
                    userVO.setPassword("*****");
                    if(StringUtils.isEmpty(userVO.getPhone())){
                        userVO.setPhone(userDTO.getPhone()
                                .replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2"));
                    }
                    return userVO;
                }).collect(Collectors.toList());
        // 封装返回结果
        PageResult<List<UserVO>> result = new PageResult<>();
        BeanUtils.copyProperties(pageResult,result);
        result.setData(userVOList);
        return ResponseResult.success(result);
    }

    /**
     * <h2>用户数据导出</h2>
     * @param query
     * @param filename
     * @return
     */
    @GetMapping("/export")
    public ResponseResult<Boolean> export(@Valid UserQueryDTO query,
                                          @NotEmpty String filename){
        log.info("接出到导出请求！");
        // 数据导出
//        excelExportService.export(query, filename);
        excelExportService.asyncExport(query,filename);
        return ResponseResult.success(Boolean.TRUE);
    }
}
